
//1. 创建套接字
//2. 绑定地址信息
//3. 开始监听
//4. 获取新连接
//5. 通过新连接接收信息
//6. 通过新连接发送信息

#include "tcpsocket.hpp"
#include <signal.h>
#include <sys/wait.h>


void sigcb(int signo)
{
    while(waitpid(-1, NULL, WNOHANG) > 0);
}
int main(int argc, char *argv[])
{
    if(argc != 3){
        printf(" em: ./tcp_cli host_ip host_port\n");
        return -1;
    }
    string ip = argv[1];
    uint16_t port = atoi(argv[2]);
    TcpSocket lst_sock;
    //if(lst_sock.Socket() == false){return -1;}
    //#define CHECK_RET(q) if((q) == false){return -1;}
    //对SIGCHLD信号进行自定义处理, 等到子进程退出的时候处理一下就可以了
    //这样就避免了父进程一直等待的情况
    signal(SIGCHLD, sigcb);
    CHECK_RET(lst_sock.Socket());
    CHECK_RET(lst_sock.Bind(ip, port));
    CHECK_RET(lst_sock.Listen());
    while(1)
    {
        TcpSocket newsock;
        string cli_ip;
        uint16_t cli_port;
        bool ret = lst_sock.Accept(&newsock, &cli_ip, &cli_port);
        if(ret == false){
            continue;
        }
        printf("new cpmmect [%s:%d]\n", cli_ip.c_str(), cli_port);
        
        pid_t pid = fork();
        if(pid == 0){
            while(1)
            {
                string buf;
                ret = newsock.Recv(&buf);
                if(ret == false) {newsock.Close(); continue;}
                printf("client say : %s\n", buf.c_str());
                printf("serve say: ");
                fflush(stdout);
                buf.clear();
                cin >> buf;
                ret = newsock.Send(buf);
                if(ret == false) { newsock.Close(); continue; }
            }
            newsock.Close();
            exit(0);
        }
        //注意: 新的套接字创建在创建子进程之前,因此父子进程各自独有一份
        //父进程并不与客户端进行通信,因此直接关闭套接字 -- 关闭的套接字是自己的,并不影响子进程
        newsock.Close();
    }
    lst_sock.Close();
    return 0;
}
